local Queue = {}

function Queue:new(capacity)
    o = {}
    setmetatable(o, self)
    self.__index = self
    self.queue = {}
    self.size_ = 0
    self.head = -1
	-- 索引相关
    self.rear = -1
    self.capacity = 0
    self.capacity = capacity
    return o
end



function Queue:enQueue(element)
    if self.size_ == 0 then
        self.head = 0
        self.rear = 1
        self.size_ = 1
        self.queue[self.rear] = element
    else
        local temp = (self.rear + 1) % self.capacity
        if temp == self.head then
            --printError("Error: capacity is full.")
            return
        else
            self.rear = temp
        end

        self.queue[self.rear] = element
        self.size_ = self.size_ + 1
    end
end

function Queue:isEmpty()
    if self:size() == 0 then
        return true
    end
    return false
end

function Queue:deQueue()
    if self:isEmpty() then
        --printError("Error: The Queue is empty.")
        return
    end
    self.size_ = self.size_ - 1
    self.head = (self.head + 1) % self.capacity
    local value = self.queue[self.head]
    return value
end

function Queue:get(idx)

    return self.queue[idx]
end

function Queue:clear()
    self.queue = nil
    self.queue = {}
    self.size_ = 0
    self.head = -1
    self.rear = -1
end



function Queue:size()
    return self.size_
end

function Queue:printElement()
    local h = self.head
    local r = self.rear
    local str = nil
    local first_flag = true
    while h ~= r do
        if first_flag == true then
            str = "{" .. self.queue[h]
            h = (h + 1) % self.capacity
            first_flag = false
        else
            str = str .. "," .. self.queue[h]
            h = (h + 1) % self.capacity
        end
    end
    str = str .. "," .. self.queue[r] .. "}"
    print(str)
end

--local Queue = require('queue')
local queue = Queue:new(7)

MAX_ACCURACY = 200 -- 默认最大值为200

--[[验证是否为合法的经纬度--]]
function isLocationValid(pos)

    if pos ~= nil then
        if math.abs(pos.lat) <= 90 and math.abs(pos.lng) <= 180 then
            return true
        end
    end
    --    saveLoad("失败原因：isLocationValid")
    return false
end

--[[验证是否在中国--]]
function isInChina(pos)
    if pos ~= nil then
        return true
    end
    --    saveLoad("失败原因：isInChina")
    return false
end

--[[验证精确度是否正确--]]
function isAccuracyValid(pos)
    if nil == pos then
        --        saveLoad("失败原因：isAccuracyValid --> pos == nil")
        return false
    elseif nil == pos.provider then
        --        saveLoad("失败原因：isAccuracyValid --> pos.provider == nil")
        return false
    elseif pos.accuracy <= MAX_ACCURACY or string.lower(pos.provider) == 'gps' then
        return true
    else
        --        saveLoad("失败原因：精度大于MAX_ACCURACY并且不是gps")
        return false
    end
end

--[[验证是否跳点--就是看当前你的速度(米/秒) 是否大于120km/h]]
function isTooFar(distance, second)
    if nil ~= distance and nil ~= second and 0 ~= second then
        local speed = (120 * 1000) / (60 * 60)
        local currentSpeed = distance / second
        return currentSpeed > speed
    end
    return false
end

--[[是否为相同的点--]]
function isSameLocation(pos1, pos2)

    local distance = getDistance(pos1, pos2)
    -- print(distance)
    if distance < 5 then
        return true
    end

    return false
end

--[[判断时间是否合法--]]
function isTimeValid(posPrev, posNow)
    return posPrev.locTime < posNow.locTime
end

--[[计算两点之间直线距离,单位为米--]]
function getDistance(pos1, pos2)

    local R = 6378137 --地球半径
    local lat1 = pos1.lat * math.pi / 180.0
    local lat2 = pos2.lat * math.pi / 180.0
    local a = lat1 - lat2
    local b = (pos1.lng - pos2.lng) * math.pi / 180.0
    local sa2 = math.sin(a / 2.0)
    local sb2 = math.sin(b / 2.0)
    local d = 2 * R * math.asin(math.sqrt(sa2 * sa2 + math.cos(lat1) * math.cos(lat2) * sb2 * sb2))

    return d
end

--[[
	判断是否全部为网络定位
--]]
function isAllNetworkLocation()
    for i = 1, queue:size() do
        if string.lower(queue:get(i).provider) == 'gps' then
            return false
        end
    end
    return true
end

--[[
	根据定位类型调整精确度
--]]
--function adjustAccuracy(pos)
--    queue:enQueue(pos)
--    if queue:size() == 6 then
--        if isAllNetworkLocation() then
--            MAX_ACCURACY = 2000; -- 网络 2000米
--        else
--            MAX_ACCURACY = 200; -- GPS 200米
--        end
--        queue:deQueue();
--    end
--end
--function adjustAccuracy(pos)
--    queue:enQueue(pos)
--    if queue:size() == 6 then
--        queue:deQueue();
--    end
--    if pos.accuracy == 'gps' then
--        MAX_ACCURACY = 200; -- 单个点 gps 精度 30米
--    else
--        MAX_ACCURACY = 2000; -- 单个点 网络 精度 200米
--    end
--end

--[[
	一分钟清空一次队列
--]]
LAST_CLEAR_TIMESTAMP = 0
function clearNetworkQueueOneMinuteInterval()

    if (os.time() - LAST_CLEAR_TIMESTAMP) > 60 then
        queue:clear()
        LAST_CLEAR_TIMESTAMP = os.time()
    end
end

--[[过滤不合法的位置信息
    posPrev 上次定位点
    posNow 现在定位点
    movetime 定位相差时间--]]
function filter(posPrev, posNow)
    clearNetworkQueueOneMinuteInterval()
    --    adjustAccuracy(posNow);
    if isLocationValid(posNow) and isInChina(posNow) then --验证是否为正确的经纬度 并且 验证是否在中国境内
        if isAccuracyValid(posNow) then --验证定位精确度是否正确
            if nil == posPrev then
                return true --第一个点
            else
                if isSameLocation(posPrev, posNow) then --判断是否没移动
                    --                    saveLoad("失败原因：isSameLocation")
                    return false
                elseif string.lower(posNow.provider) == 'gps' then
                    local movetime = posNow.locTime - posPrev.locTime --计算定位时间差
                    local distance = getDistance(posPrev, posNow) --计算定位点之间的距离
                    if isTooFar(distance, movetime) then --判断是否跳点
                        return false
                    else
                        return true
                    end
                else
                    local movetime = posNow.locTime - posPrev.locTime --计算定位时间差
                    local distance = getDistance(posPrev, posNow) --计算定位点之间的距离
                    if isTooFar(distance, movetime) then --判断是否跳点
                        --                        saveLoad("失败原因：isTooFar")
                        return false
                    else
                        if isTimeValid(posPrev, posNow) then -- 判断时间是否合法
                            --                    saveLoad("失败原因：isTimeValid")
                            return true
                        else
                            return false
                        end
                    end
                end
            end
        end
        --    saveLoad("失败原因：都没通过")
        return false
    end
end

--function saveLoad(text)
--    local path = "/storage/emulated/0";
--    txtpath = path .. "/xiaoka/point.txt"
--    local file = io.open(txtpath, "a+") --以“写入”方式打开文件，如果文件不存在则创建
--    file:write(text) --写入信息
--    file:write("\r\n") --换行
--    file:close()
--end

